var Ui =
{
    innerLayouts: new Array(),
    username: "",
    isConnected: false,
    
    on_message_get_chat: function(full_jid, messageText, isDelayedMessage)
    {
        var jid = Strophe.getBareJidFromJid(full_jid);
        if (Ui.isChattingWith(jid) === false)
        {
            var name = Ui.getContactName(jid);
            if (name === "")
                name = jid;
            Ui.createChatTab(full_jid, name);
        }
        else
        {
            Ui.selectChatTab(jid);
        }
        
        Ui.setChatTabData(full_jid); 
        Ui.appendChatMessage(false, jid, messageText, isDelayedMessage);
        Ui.scrollChat(jid);         
    },
    
    on_presence_subscription_request: function(requesterJid)
    {
    	Ui.showPresenceRequestApprovalDialog(requesterJid);
    },
    
    on_presence_contact_show_change: function(from, show)
    {
    	Ui.setContactPresenceShow(from, show);
    },
    
    on_presence_contact_status_change: function(from, status)
    {
    	Ui.setContactPresenceStatus(from, status);
    },

    on_presence_contact_resource_change: function(full_jid)
    {
    	Ui.setChatTabData(full_jid);
    },
    
    on_connection_status_changed: function(status)
    {
    	var statusText = "";
    	
        if (status === Strophe.Status.CONNECTING)
        {
           Ui.enableAccountsPane(false);
           statusText = "Connecting to server ...";
        }
        else if (status === Strophe.Status.AUTHENTICATING)
        {
           Ui.enableAccountsPane(false);
           statusText = "Authenticating to server ...";
        }        
        else if (status === Strophe.Status.CONNECTED)
        {
           Ui.enableAccountsPane(true);
           statusText = "Connected to server as '" + username + "'";
        }      
        else if (status === Strophe.Status.DISCONNECTING)
        {
           Ui.enableAccountsPane(false);
           statusText = "Disconnecting from server ...";
        }        
        else if (status === Strophe.Status.DISCONNECTED)
        {
           Ui.enableAccountsPane(true);
           statusText = "Disconnected from server";
        }
        else if (status === Strophe.Status.CONNFAIL)
        {
           Ui.enableAccountsPane(true);
           statusText = "Failed to connect to server";
        }
        else if (status === Strophe.Status.AUTHFAIL)
        {
           Ui.enableAccountsPane(true);
           statusText = "Failed to authenticate to server";
        }
        
        isConnected = (status === Strophe.Status.CONNECTED) ? true : false ;
        Ui.setLayout(isConnected);
        Ui.setStatusText(statusText);
    },
    
    on_roster_get: function(jid, name, show, status)
    {
    	Ui.insertContact(jid, name, show, status);
    },
    
    on_roster_replace: function(jid, name)
    {
    	Ui.replaceContact(jid, name);
    },

    on_roster_remove: function(jid)
    {
    	Ui.removeContact(jid);
    },
    
    on_menu_item_click: function(dropmenuText)
    {
		if (dropmenuText === "Help")
		{
			$("body #centerTabs").tabs("select", "tabWelcome");
		}
		else if (dropmenuText === "Tic Tac Toe")
		{
			$("body #centerTabs").tabs("select", "tabTicTacToe");
		}
		else if (dropmenuText === "Exit application")
		{
			if (window.confirm("Are you sure you want to sign out and close this browser window?")) 
			{ 
				Ui.disconnect();
				window.close();
			}
		}
		else if (dropmenuText == "Sign in")
		{
			Ui.showWestPane();
			Ui.setLayout(false);
			$("input#username").val("");
			$("input#password").val("");
			// $("input#username").css("background", "yellow");
			$("input#username").focus();
		}
		else if (dropmenuText == "Sign up")
		{
			Ui.showWestPane();
			Ui.setLayout(false);
			$("input#newUsername").focus();
		}	
		else if (dropmenuText == "Sign out")
		{
			Ui.disconnect();
		}	
		else
		{
			alert(dropmenuText + " menu item not yet implemented.");   
		}
    },
    
    connect: function()
    {
        username = Ui.getUserJid();
        var password = Ui.getUserPassword();
        log("Connecting ", username, " with password ", password);
        
        if ((username !== null && username !== undefined && username !== "") 
        		&& (password !== null && password !== undefined && password !== ""))
        {
        	Xmpp.connect(username, password);
        }
        else
        {
        	alert("Please enter your Jabber user name and password and retry.");
        }
    },
    
    signup: function()
    {
        var username = $("input#newUsername").val();
        var password1 = $("input#newPassword").val();
        var password2 = $("input#newPassword2").val();
        if (username === null || username === undefined || username.length == 0 
                        || password1 === null || password1 === undefined ||  password1.length == 0 || password1 != password2)
        {
            alert("No passwords entered, or the passwords you entered do not match.\nPlease retry.");
        }  
        else
        {
        	// Sample code: 
        	// http://stackoverflow.com/questions/9645647/return-json-from-servlet
        	
        	// http://code.google.com/p/jquery-json/ : 
        	// var thing = {plugin: 'jquery-json', version: 2.3}; 
        	// var encoded = $.toJSON( thing ); 
        	// // '{"plugin":"jquery-json","version":2.3}' 
        	// var name = $.evalJSON( encoded ).plugin; 
        	// // "jquery-json" var version = $.evalJSON(encoded).version; // 2.3
        	
        	// CORS Filter: http://software.dzhuvinov.com/cors-filter-installation.html
        	
        	var request = {username : username, password : password1};
        	var encodedRequest = $.toJSON(request);
            //var url = "http://ec2-23-20-11-152.compute-1.amazonaws.com:8080/xmppsrv/CreateJabberAccount";
            var url = "http://localhost:8084/xmppsrv/CreateJabberAccount";
            $.ajax({
                url: url
              , type: 'POST'
              , dataType: 'json'
              , data: { parameters: encodedRequest }
              , success: function(jsonResponse) 
              {
            	  $.each(jsonResponse, function(key, val) {
            		    alert("Your request result: " +  val);
            		  });
              }
              , error: function(xhr,err) 
              {
                  alert('Ajax readyState: ' + xhr.readyState + '\nstatus: ' + xhr.status + ' ' + err);
              }
            });  	
            
        }
    },
    
    disconnect : function()
    {
        Xmpp.disconnect();
        username = "";
    },
    
    assertJid: function(jid, functionName)
    {
        if (Ui.isContact(jid) == false)
        {
            // throw new Error(functionName + ": invalid jid: " + jid);
            log("**** WARNING: " + functionName + ": invalid jid: " + jid);
        }
    },

    getUserJid: function()
    {
       return $("#username").val();
    },

    getUserPassword: function()
    {
       return $("#password").val();
    },

    getIdFromJid: function (jid)
    {
        return Strophe.getBareJidFromJid(jid).replace("@", "-").replace(/\./g, "-");
    },

    createContactListItem: function(jid, name, presenceShow, presenceStatus)
    {
        var jid_id = Ui.getIdFromJid(jid);

        if (presenceShow === undefined || presenceShow === null)
            presenceShow = "xa";

        if (presenceStatus === undefined || presenceStatus === null)
            presenceStatus = "";

        var contactListItem = $("<li id='" + jid_id + "'>" +
                                    "<div class='roster-contact " + presenceShow + "'>" +
                                        "<div class='roster-name'>" + name + "</div>" +
                                        "<div class='roster-jid'>" + Strophe.getBareJidFromJid(jid) + "</div>" +
                                        "<div class='roster-show'>" + presenceShow + "</div>" +
                                        "<div class='roster-status'>" + presenceStatus + "</div>" +
                                    "</div>" +
                                "</li>");

        return contactListItem;
    },

    removeAllContacts: function()
    {
        $("#roster-area li").remove();
    },

    setContactPresenceStatus: function(jid, presenceStatus)
    {
        Ui.assertJid(jid, "setContactPresenceStatus");

        var success = false;
        if (Ui.isContact(jid) === true)
        {
            var jidId = Ui.getIdFromJid(jid);
            var contactStatus = $('#roster-area li#' + jidId + ' .roster-status');
            contactStatus.text(presenceStatus);
            success = true;
        }
        return success;
    },

    setContactPresenceShow: function(jid, presenceShow)
    {
        Ui.assertJid(jid, "setContactPresenceShow");

        var success = false;
        if (Ui.isContact(jid) === true)
        {
            var jidId = Ui.getIdFromJid(jid);
            var name = Ui.getContactName(jidId);
            var presenceStatus = Ui.getContactPresenceStatus(jid);
            $('#roster-area li#' + jidId).remove();
            Ui.insertContact(jid, name, presenceShow, presenceStatus);
            success = true;
        }
        return success;
    },

    getContactName: function(jid)
    {
        Ui.assertJid(jid, "getContactName");

        if (Ui.isContact(jid) === true)
        {
            var jid_id = Ui.getIdFromJid(jid);
            return $("#roster-area li#" + jid_id + " .roster-name").text();
        }
        return "";
    },

    getContactPresenceShow: function(jid)
    {
        Ui.assertJid(jid, "getContactPresenceShow");

        if (Ui.isContact(jid) === true)
        {
            var jidId = Ui.getIdFromJid(jid);
            var contact = $('#roster-area li#' + jidId + ' .roster-contact');
            for (var show_value in Xmpp.show_values)
            {
                if (contact.hasClass(Xmpp.show_values[show_value]))
                    return Xmpp.show_values[show_value];
                ++show_value;
            }
        }
        return Xmpp.show_values[0];
    },

    getContactPresenceShowValue : function(presenceShow)
    {
        var show_value = 0;
        if (typeof presenceShow === "object")
        {
            for (show_value in Xmpp.show_values)
            {
                if (presenceShow.hasClass(Xmpp.show_values[show_value]))
                    return show_value;
                ++show_value;
            }
        }
        else if (typeof presenceShow === "string")
        {
            for (show_value in Xmpp.show_values)
            {
                if (presenceShow === Xmpp.show_values[show_value])
                    return show_value;
                ++show_value;
            }
        }
        return 0;
    },

    getContactPresenceStatus: function(jid)
    {
        Ui.assertJid(jid, "getContactPresenceStatus");

        if (Ui.isContact(jid) === true)
        {
            var jid_id = Ui.getIdFromJid(jid);
            return $("#roster-area li#" + jid_id + " .roster-status").text();
        }
        return "";
    },

    isContact: function(jid)
    {
        var jidId = Ui.getIdFromJid(jid);
        return $("#" + jidId).length > 0 ? true : false ;
    },

    replaceContact: function(jid, name)
    {
        Ui.assertJid(jid, "replaceContact");

        var success = false;
        if (Ui.isContact(jid) === true)
        {
            var show = Ui.getContactPresenceShow(jid);
            var status = Ui.getContactPresenceStatus(jid);
            var contactListItem = Ui.createContactListItem(jid, name, show, status);
            var jidId = Ui.getIdFromJid(jid);
            $("#" + jidId).replaceWith(contactListItem);
            success = true;
        }
        return success;
    },

    removeContact: function(jid)
    {
        Ui.assertJid(jid, "removeContact");

        var success = false;
        if (Ui.isContact(jid) === true)
        {
            var jidId = Ui.getIdFromJid(jid);
            $("#" + jidId).remove();
            success = true;
        }
        return success;
    },

    insertContact : function(jid, name, show, status)
    {
        log ("Ui.insertContact : jid: " + jid + " name: " + name + " show: " + show + " status: " + status);

        var inserted = false;
        if (Ui.isContact(jid) == false)
        {
            var jidId = Ui.getIdFromJid(jid);
            var contactListItem = Ui.createContactListItem(jid, name, show, status);
            var showValue = Ui.getContactPresenceShowValue(show);
            var contacts = $('#roster-area li');
            if (contacts.length > 0)
            {
                contacts.each
                (
                    function()
                    {
                        var itemShow = Ui.getContactPresenceShow($(this).attr("id"));
                        var itemShowValue = Ui.getContactPresenceShowValue(itemShow);
                        var itemJid    = $(this).find('.roster-jid').text();
                        var itemJidId = Ui.getIdFromJid(itemJid);

                        if ((itemShowValue === showValue && jidId < itemJidId) || itemShowValue < showValue)
                        {
                            $(this).before(contactListItem);
                            inserted = true;
                            return false;
                        }
                        return true;
                    }
                );

                if (!inserted)
                {
                    $('#roster-area ul').append(contactListItem);
                    inserted = true;
                }
            }
            else
            {
                $('#roster-area ul').append(contactListItem);
                inserted = true;
            }
        }

        return inserted;
    },

    getTabId: function(type, jid)
    {
        var jidId = Ui.getIdFromJid(jid);
        var tabId = "#" + type + "-" + jidId;
        return tabId;
    },
    
    setChatTabData: function(jid)
    {
        var success = false;
        if (Ui.isChattingWith(jid) === true)
        {
            var user_chat_tab_id = Ui.getTabId("chat", jid);
            $(user_chat_tab_id + " button.chat-text-send").attr("jid", jid);
            success = true;
        }
        return success;
    },
    
    createChatTab: function (jid, name)
    {
        var user_chat_tab_id = Ui.getTabId("chat", jid);
        $("#centerTabs").tabs("add", user_chat_tab_id, name);
        $(user_chat_tab_id).addClass("tab-panel-with-inner-layout");
        $("#centerTabs").tabs("select", user_chat_tab_id);
        $(user_chat_tab_id).append
        (
                "<div class='ui-layout-center chat-messages'>" + 
                "<p>Chat messages:</p>" +
                "</div>" +
                "<div class='ui-layout-south'>" + 
                    "<div id='chat-input-header'>Writing a message to " + name + ". Press button to ... <button class='chat-text-send' type='button' jid='" + jid + "'>send!</button></div>" +
                    "<textarea class='chat-input ui-layout-content' type='text'></textarea>" +
                "</div>"
        );
        
        Ui.setChatTabData(jid);
        Ui.createChatTabLayout(jid);
        Ui.selectChatTab(jid);
    },
    
    createChatTabLayout: function(jid)
    {
        var user_chat_tab_id = Ui.getTabId("chat", jid);
        var newLayout = $('body #centerTabs ' + user_chat_tab_id).layout({ south__resizable: true
                                                                            , south__closable:  false
                                                                            });
        Ui.innerLayouts[user_chat_tab_id] = newLayout;  
    },
    
    selectChatTab: function(jid)
    {
        var user_chat_tab_id = Ui.getTabId("chat", jid);
        $("body > .ui-layout-center").tabs("select", user_chat_tab_id);
        $(user_chat_tab_id + " textarea").focus();
    },

    appendChatMessage: function(isMe, jid, body_text, isDelayedMessage)
    {
        var user_chat_tab_id = Ui.getTabId("chat", jid);

        var messageContent = $("<div class='chat-message-" + (isMe? "myself" : "other") + "'" + (isDelayedMessage ? " delayed " : "") + ">" +
                                    "&lt;<span class='chat-name'>" +
                                        (isMe ? "myself" : Strophe.getNodeFromJid(jid)) +
                                    "</span>&gt;" +
                                    "<span class='chat-text'>" +
                                        body_text +
                                    "</span>" +
                               "</div>");

        var temp = $(user_chat_tab_id + " .chat-messages").length;
        $(user_chat_tab_id + " .chat-messages").append(messageContent);
    },

    scrollChat: function(jid)
    {
        var jid_id = Ui.getIdFromJid(jid);
        var user_chat_messages = "#chat-" + jid_id + " .chat-messages";
        log("number of chat messages : " + $(user_chat_messages).length);
        var domDiv = $(user_chat_messages).get(0);
        domDiv.scrollTop = domDiv.scrollHeight;
    },

    isChattingWith: function(jid)
    {
        var user_chat_tab_id = Ui.getTabId("chat", jid);
        return ($(user_chat_tab_id).length > 0) ? true : false ;
    },

    showContacts: function()
    {
        $("#west_accordion").accordion( "activate" , "#buddies" );
    },

    showAccount: function()
    {
        $("#west_accordion").accordion( "activate" , "#account" );
    },
    
    showWestPane: function()
    {
    	myLayout.sizePane("west", 300);
    },
    
    showPresenceRequestApprovalDialog: function(requesterJid)
    {
        log("Ui.showPresenceRequestApprovalDialog: startging. requesterJid : " + requesterJid);

        $("#approveJid").text(requesterJid);
        $("#approveDialog").dialog("open");

        log("Ui.showPresenceRequestApprovalDialog: exiting.");
    } ,
    
    setStatusText: function(status)
    {
    	$("span#status").text(status);
    },
    
    enableAccountsPane: function(enable)
    {
    	if (enable === true)
    	{
    		$('#west_accordion').hideLoading();
    		myLayout.enableResizable("west");
    		myLayout.enableClosable("west"); 
    	}
    	else if (enable === false)
    	{
    		$('#west_accordion').showLoading(); 
    		myLayout.disableResizable("west");
    		myLayout.disableClosable("west"); 
    	}
    },
    
    setLayout: function(connected)
    {
        if (connected)
        {
           $("#connection_create").addClass("hidden");
           $("#connection_destroy").removeClass("hidden");
           Ui.showContacts();  
           $("button#addContact").removeAttr("disabled");
           $("span#roster-area-help").css("display", "none");
           
           $("a#signout").removeAttr('disabled');
           $("a#signin").attr('disabled', 'disabled');  
           $("a#signup").attr('disabled', 'disabled'); 
        }
        else
        {
           $("#connection_create").removeClass("hidden");
           $("#connection_destroy").addClass("hidden");  
           Ui.removeAllContacts();
           Ui.showAccount();
           $("button#addContact").attr("disabled", "disabled");
           $("span#roster-area-help").css("display", "block");
           
           $("a#signout").attr('disabled', 'disabled');  
           $("a#signin").removeAttr('disabled');
           $("a#signup").removeAttr('disabled');
        }   	
    }
    
};

var tabsLayout = null;
var myLayout = null;

//options for the layout generated _inside_ the tab(s)
var tabLayoutOptions = 
{
			 resizeWithWindow:           false // *** IMPORTANT *** tab-layouts must NOT resize with the window
	//	,    center__contentSelector:    ".ui-widget-content"
		,    north__closable:            false
		,    north__size:    			"80%"    
};

$(function()
{
    myLayout = $('body').layout
    ({
        			west__size:         300
        		,   east__size:         300
        		,   west__maxSize:		300 
        		,   east__maxSize:		300 
        		// RESIZE Accordion widget when panes resize
        		,   west__onresize:     $.layout.callbacks.resizePaneAccordions
        		,   east__onresize:     $.layout.callbacks.resizePaneAccordions
        		,   center__onresize:   $.layout.callbacks.resizeTabLayout
        		, 	north__resizable: 	false
        		, 	south__resizable: 	false 
    });
   
    tabsLayout = $('body  #centerTabs').layout
    ({ 				
    				north__resizable: 	false 
    			, 	north__closable:  	false
    			, 	center__onresize:   $.layout.callbacks.resizeTabLayout
    			, 	resizeWithWindow:   false
    });
    
    $("#west_accordion").accordion({ fillSpace:    true });
    
    // ACCORDION - in the East pane
    $("#accordion2").accordion
    ({
        			fillSpace:    true
        		,   active:       1
    });

    $Tabs = $("body #centerTabs").tabs
    ({
        // runs after widget generates a new tab-button and tab-panel
        add: function (evt, ui ) 
        {
            $Tabs.tabs("disable"); // will enable in tabs.load method
            // MOVE the auto-generated panel inside the panels-wrapper DIV
            $( ui.panel ).appendTo( "#tabPanels" );
            // resize tabs-layout in case tabs now wrap to another line
            $Tabs.layout().resizeAll();
            // automatically select the newly added tab
            $Tabs.tabs( "select", ui.index );
        }
        
        // runs after widget removes a tab
        , remove: function (evt, ui ) 
        {
            $Tabs.layout().resizeAll();
        }
        
        //    runs after a tab is made visible - but before Ajax content is loaded
        //    this will also run when the tabs widget initializes - and the first tab-panel is shown
        ,    show: $.layout.callbacks.resizeTabLayout // resize the layout inside tab - if one exists

        ,    show_ALTERNATE: function (evt, ui) {
                // resize inner tab-layout(s), if are any
                $.layout.callbacks.resizeTabLayout(evt, ui);
                // resize Accordion(s), if are any
                // REQUIRES the jquery.layout.resizePaneAccordions.xx.js callback loaded
                //$.layout.callbacks.resizePaneAccordions(evt, ui);
            }

        //    runs after widget finishes loading Ajax content into a tab
        ,    load: function (evt, ui ) { 
                // look for layout-options data on the *first element* of the injected content
                // this trick could also be used to trigger initialization of other widgets, like tabs or accordions
                var $panel        = $( ui.panel )
                // see if data exists AND that there is an object with that name
                ,    optsName    = $panel.children(":first").data("layout_options") // eg: "tabLayoutOptions"
                ,    options        = window[ optsName ]
                ;
                // if layout options found, then init the layout with these options
                if (options)
                    $panel.layout( options );
                // now re-enable the tabs widget - loading has completed
                $Tabs.tabs("enable");
            }
        
        //    runs after widget is created and the first tab is shown
        ,    create: function (evt, ui ) { 
                // create the layout inside the first tab
                //$("#tabWelcome").layout( tabLayoutOptions );
                //$("#tabTicTacToe").layout( tabLayoutOptions );
            }
        
        , select: function(evt, ui){
            $( ui.panel ).css("display", "block");
        }
    });
    
    tabsLayout.resizeAll();
    isConnected = false;
    Ui.setLayout(isConnected);
    Ui.setStatusText("Welcome, guest is not logged in");

    // BEGIN For debug purposes only
    $("#username").val("gamersweb_qa1@jabber.org")
    $("#password").val("gamersweb1")
    // END For debug purposes only

    $("#connection_destroy").addClass("hidden");
    $("button#xmpp_connect").click(Ui.connect);
    $("button#xmpp_create").click(Ui.signup);
    $("button#xmpp_disconnect").click(Ui.disconnect);
    
    $("#contactDialog").dialog
    (
        {
            autoOpen: false,
            draggable:true,
            modal:false,
            title:"Add a contact",
            buttons:
            {
                "Add" : function()
                {
                    Xmpp.add_contact({jid:$("#contactId").val(), name:$("#contactName").val()});
                    $("#contactId").val("");
                    $("#contactName").val("");
                    $(this).dialog("close");
                }
            }
        }
    );

    $("button#addContact").click
    (
       function()
       {
           $("#contactDialog").dialog("open");
       }
    );

    $("#approveDialog").dialog
    (
        {
            autoOpen: false,
            draggable: true,
            modal: false,
            title: "Subscription Request",
            buttons:
            {
               "Deny": function()
               {
                   log("approveDialog Deny: starting.");

                   Xmpp.connection.send($pres({to: Xmpp.pending_subscriber, type: "unsubscribed"}));
                   Xmpp.pending_subscriber = null;
                   $(this).dialog("close");

                   log("approveDialog Deny: exiting.");
               },

               "Approve": function()
               {
                   log("approveDialog Approve: starting.");
                   
                   // Approve request.
                   Xmpp.connection.send($pres({to: Xmpp.pending_subscriber, type: "subscribed"}));

                   // Request other side's presence.... hmmm.... do this depending on a check box to be added to the dialog.
                   // Xmpp.connection.send($pres({to: Xmpp.pending_subscriber, "type": "subscribe"}));
                   Xmpp.pending_subscriber = null;
                   $(this).dialog("close");

                   log("approveDialog Approve: exiting.");
               }
            }
        }
    );

    $(".roster-contact").live
    (
        "click",
        function()
        {
            var jid = $(this).find(".roster-jid").text();
            var name = $(this).find(".roster-name").text();
            var user_chat_tab_id = Ui.getTabId("chat", jid);

            log("number of " + user_chat_tab_id + " tabs is : " + $(user_chat_tab_id).length);
            if (Ui.isChattingWith(jid) === false)
            {
                Ui.createChatTab(jid, name);
            }
            else
            {
                Ui.selectChatTab(jid);
            }
        }
    );

    $(".chat-text-send").live
    (
        "click",
        function(event)
        {
            event.preventDefault();
            var jid = $(this).attr("jid");
            var user_chat_tab_id = Ui.getTabId("chat", jid);
            var chatInputElement = $(user_chat_tab_id + " textarea.chat-input"); 
            var body_text = chatInputElement.val();
            if (body_text === "")
            	return;
            
            Xmpp.connection.send($msg({to: jid, type: "chat"}).c("body").t(body_text));
            Ui.appendChatMessage(true, jid, body_text, false);
            Ui.scrollChat(jid);
            chatInputElement.val("");
            chatInputElement.focus();
        }
    );
    
    $("#tabButtons span.ui-icon-close").live
    (
    	"click", 
    	function() 
    	{
    		var index = $("li", $Tabs).index($(this).parent());
    		$Tabs.tabs("remove", index);
    	}
    );    
});